<template>
<!-- 一层楼有十个房间的楼层 -->
    <div>
        <div id="container" ref="container">
        </div>
        <!-- 显示加载过程的进度条 -->
        <!-- <div style="position: absolute;width:400px;" :style="{left: left+'px',top: top+'px'}">
            <el-progress v-if="loadedData!==100" :text-inside="true" :stroke-width="30" :percentage="loadedData"></el-progress>
        </div> -->
        <!-- 显示当前楼层的下拉框 -->
        <!-- <div class="floor-select">
            <el-select v-model="selectedFloorId" popper-class="select-option" placeholder="请选择" > 
                <el-option
                v-for="item in floorList"
                :key="item.id"
                :label="item.floorName"
                :value="item.id">
                </el-option>
            </el-select>
        </div> -->
        <!-- 返回整栋楼页面 测试用 -->
        <div class="back-building">
            <a style="display:table-cell; text-align: center; vertical-align:middle; font-size:0.2rem; color:white" @click="toBuilding()">返回</a>
        </div>
    </div>
</template>

<script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
import Stats from 'stats.js/build/stats.min.js'

// 定义three全局变量
const scene = new THREE.Scene;
// three的控制器必须放在data外，否则会造成卡顿
let controls;
// 帧率显示插件
let stats;

export default {
    data() {
        return {
            // 初始化threejs使用的参数
            camera: null,
            renderer: null,
            tick: null,
            // 点击到的房间号码
            roomNum: '',
            // 存储被选中的房间的数组
            roomOnSelect: [],
            // 是否有房间已经被选中
            isSelect: false,
            // 所有楼层
            floorList: [{
                id: '4',
                floorName: '第4层'
            },{
                id: '5',
                floorName: '第5层'
            },{
                id: '6',
                floorName: '第6层'
            },{
                id: '7',
                floorName: '第7层'
            },{
                id: '8',
                floorName: '第8层'
            },{
                id: '9',
                floorName: '第9层'
            },{
                id: '13',
                floorName: '第13层'
            }],
            // 选中的楼层
            selectedFloorId: '',
        };
    },
    created() {
        // 监听鼠标点击
        window.addEventListener("dblclick", this.onMouseDblclick, true)
        // 监听浏览器窗口的改变
        window.addEventListener('resize',this.onWindowResize,false)
    },
    mounted() {
        this.init();
        this.animate();
        this.addModels();
    },
    destroyed() {
        // 离开当前页面的时候，销毁相关的鼠标监听事件
        window.removeEventListener("dblclick", this.onMouseDblclick, true)
        window.removeEventListener('resize',this.onWindowResize,false)
    },
    computed: {
        floor() {
            return this.$store.state.floorNumber
        }
    },
    methods: {
        //初始化
        init() {
            // 创建场景对象Scene
            this.scene = new THREE.Scene();
            // 相机设置
            let container = this.$refs.container
            this.camera = new THREE.PerspectiveCamera(
                70,
                container.clientWidth / container.clientHeight,
                0.01,
                1000
            );
            this.camera.position.set(55,45,65)
            // 光线
            this.scene.add(new THREE.AmbientLight(0xffffff));
            // 创建渲染器对象
            this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha:true, powerPreference: "high-performance"});
            this.renderer.setSize(container.clientWidth, container.clientHeight);
            container.appendChild(this.renderer.domElement);
            // 创建控件对象
            this.controls = new OrbitControls(this.camera, this.renderer.domElement);
            // 坐标轴辅助工具
            // let helper = new THREE.AxesHelper(50);
            // this.scene.add(helper);
            // 显示帧率
            // this.stats = new Stats()
            // container.appendChild(this.stats.dom)
            // 启用浏览器调试插件
            // window.scene = this.scene;
            // window.THREE = THREE;
        },
        // 动画
        animate() {
            // this.stats.update();
            this.tick = requestAnimationFrame(this.animate)
            this.renderer.render(this.scene, this.camera)
        },
        // 根据窗口变化更改显示大小
        onWindowResize() {
            this.camera.aspect = this.$refs.container.clientWidth / this.$refs.container.clientHeight
            this.camera.updateProjectionMatrix()
            this.renderer.setSize(this.$refs.container.clientWidth, this.$refs.container.clientHeight)
        },
        //导入模型
        addModels() {
            let loader = new FBXLoader()
            // 导入分割过房间的模型，一层一共有十个房间
            // 供4、5层使用
            loader.load('models/Three/single_floor/13F_分割版.fbx',obj => {
                this.scene.add(obj)
                console.log(this.scene);
                // 调整模型位置和角度
                obj.position.set(30, -75, 10)
                obj.rotation.x = -1.57
                obj.scale.set(0.5, 0.5, 0.5)
                // 修改模型材质
                this.setTexture()
            },xhr => {
                console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' )
                // 把加载进度数据取整然后传递给进度条
                this.loadedData = Math.floor( xhr.loaded / xhr.total*100 )
            })
        },
        // 调整模型的材质美化模型外观
        setTexture() {
            // 将房间实体的透明度调低，使房间实体透明
            for (let index = 0; index < 10; index++) {
                this.scene.children[1].children[3].children[4].children[index].children[0].material.transparent = true
                this.scene.children[1].children[3].children[4].children[index].children[0].material.opacity = 0
            }
            // 修改玻璃幕墙的MeshPhongMaterial材质，使玻璃幕墙透明
            for (let index = 0; index < 266; index++) {
                this.scene.children[1].children[3].children[2].children[0].children[0].children[index].children[0].children[0].material.transparent = true
                this.scene.children[1].children[3].children[2].children[0].children[0].children[index].children[0].children[0].material.opacity = 0.2
                this.scene.children[1].children[3].children[2].children[0].children[0].children[index].children[0].children[0].material.specular = {r: 0.8549019694328308, g: 0.8901960849761963, b: 0.8549019694328308}
            }
            // 修改地板的颜色，避免曝光过度
            this.scene.children[1].children[3].children[5].children[0].children[0].children[1].children[0].material.color = {r: 0.8, g: 0.8, b: 0.8}
        },
        // 射线检测获取与射线相交的对象数组
        getIntersects(event) {
            // 声明 raycaster 和 mouse 变量
            let raycaster = new THREE.Raycaster()
            let mouse = new THREE.Vector2()
            mouse.x = (event.clientX / this.$refs.container.clientWidth) * 2 - 1
            mouse.y = -(event.clientY / this.$refs.container.clientHeight) * 2 + 1
            // 通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
            raycaster.setFromCamera(mouse, this.camera)
            // 获取与射线相交的对象数组，其中的元素按照距离排序，越近的越靠前
            let intersects = raycaster.intersectObjects(this.scene.children, true)
            console.log(intersects);
            //返回选中的对象
            return intersects
        },
        // 鼠标双击，返回选中的房间号并将该房间进行颜色标识
        onMouseDblclick(event) {
            // 调用射线检测，获得鼠标点击位置的模型实体
            let intersects = this.getIntersects(event)
            // 判断鼠标点击的位置是否为房间
            if ( intersects.length != 0 && intersects[0].object.parent.name.indexOf("房间") != -1){
                // 点击之后给该房间的标记上颜色
                this.drawRoom(intersects[0].object)
                // 返回点击的房间号
                this.roomNum = this.getRoomNum(intersects[0].object.parent.name)
                this.$message.success('当前点击房间号：' + this.roomNum)
            }
            else return
        },
        // 给房间进行颜色标识，同一时间只允许有一个房间被涂色
        drawRoom (room) {
            // 判断是否有房间已经被选中
            // 尚未有房间被选中，是第一次进行点击
            if(this.isSelect === false){
                room.material = new THREE.MeshLambertMaterial({
                    color: 0x409EFF,
                    transparent: true, 
                    opacity: 0.7,
                })
                this.roomOnSelect.push(room)
                this.isSelect = true
            }
            // 已有房间被选中
            else{
                // 当前点击的不是已经选中过的房间
                if(this.roomOnSelect[0] !== room){
                    this.roomOnSelect[0].material = new THREE.MeshLambertMaterial({ 
                        color: 0x409EFF, 
                        transparent: true, 
                        opacity: 0,
                    })
                    this.roomOnSelect.pop()
                    room.material = new THREE.MeshLambertMaterial({
                        color: 0x409EFF,
                        transparent: true, 
                        opacity: 0.7,
                    })
                    this.roomOnSelect.push(room)
                }
                // 点击的是已选中过的房间
                else{
                    if(this.roomOnSelect[0].material.opacity !== 0){
                        this.roomOnSelect[0].material.opacity = 0
                    }
                    else {
                        this.roomOnSelect[0].material.opacity = 0.7
                    }
                } 
            }
        },
        // 根据当前所在楼层，返回对应的房间号码
        getRoomNum(room) {
            // 楼层号存储在sessionStorage中，防止刷新之后楼层号失效
            let floor = window.sessionStorage.getItem('floorNumber')
            let roomNumber = floor.toString() + room.slice(4, 6)
            return roomNumber
        },
        // 销毁场景释放缓存
        clearCache() {
            this.renderer.dispose()
            this.renderer.forceContextLoss()
            window.cancelAnimationFrame(this.tick)
            // this.renderer.context = null
            this.renderer.domElement = null
            this.renderer = null
            this.scene = null
            this.camera = null
            this.controls = null
        },
        // 返回整栋楼的界面
        toBuilding() {
            // 销毁当前页面中threejs场景，释放浏览器缓存
            this.$router.push('/building')
            this.clearCache() 
        }
    }  
}
</script>

<style lang="less" scoped>
#container {
  position: absolute;
  width: 100%;
  height: 100%;
  background-image: url("../../assets/images/background.png");
  background-size: cover;
}   
.back-building{
    width: 0.8rem;
    height: 0.4rem;
    position: absolute;
    right: 2rem;
    top: 2rem;
    z-index: 1;
    border: 1px sloid #666;
    background: rgba(110, 114, 117, 0.6);
    border-radius: 3px;
    display: table;
    cursor: pointer;
    // border: 1px solid greenyellow;
} 
.floor-select{
    width: 3rem;
    height: 0.8rem;
    position: absolute;
    left: 2rem;
    bottom: 2rem;
}
// element下拉框样式
.select-option{
    background-color: transparent !important;
}
</style>